home *** CD-ROM | disk | FTP | other *** search
/ Language/OS - Multiplatform Resource Library / LANGUAGE OS.iso / cpp_libs / csim / source.lha / source / Threads / GnuThreads / clk.c < prev    next >
Encoding:
C/C++ Source or Header  |  1993-06-14  |  2.6 KB  |  100 lines

  1. /*
  2.  * clk.c -- timer routines for lightweight processes.
  3.  * Copyright (C) 1991 Stephen Crane.
  4.  *
  5.  * This is free software; you can redistribute it and/or modify
  6.  * it under the terms of the GNU General Public License as published by
  7.  * the Free Software Foundation; either version 1, or (at your option)
  8.  * any later version.
  9.  *
  10.  * This software is distributed in the hope that it will be useful,
  11.  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  12.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  13.  * GNU General Public License for more details.
  14.  *
  15.  * You should have received a copy of the GNU General Public License
  16.  * see the file COPYING.  If not, write to
  17.  * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
  18.  *
  19.  * author: Stephen Crane, (jsc@doc.ic.ac.uk), Department of Computing,
  20.  * Imperial College of Science, Technology and Medicine, 180 Queen's
  21.  * Gate, London SW7 2BZ, England.
  22.  */
  23.  
  24. #include <sys/types.h>
  25. #include <sys/time.h>
  26. #include <signal.h>
  27. #include "gnulwp.h"
  28.  
  29. /* delta queue for the timer */
  30. static struct lpq delayq;
  31.  
  32. /*
  33.  * timersub calculate to=a-b; for timevals.  assumes a>b
  34.  */
  35. static void timersub (struct timeval *to, struct timeval *a, struct timeval *b)
  36. {
  37.     if (a->tv_usec < b->tv_usec) {
  38.         a->tv_usec += 1000000;
  39.         a->tv_sec--;
  40.     }
  41.     to->tv_usec = a->tv_usec - b->tv_usec;
  42.     to->tv_sec = a->tv_sec - b->tv_sec;
  43. }
  44.  
  45. /*
  46.  * delay -- block the invoker for >t microseconds.  If t==0, reschedule.
  47.  */
  48. void delayp (long ut)
  49. {
  50.     extern struct pcb *currp;
  51.  
  52.     if (ut) {
  53.         struct pcb *p=delayq.head, *q=0;
  54.         struct itimerval itime;
  55.         struct timeval t, *left = &itime.it_value;
  56.         t.tv_sec = ut/1000000;
  57.         t.tv_usec = ut%1000000;
  58.         if (p) {
  59.             getitimer (ITIMER_REAL, &itime);
  60.             if (timercmp(left, &t, >)) {
  61.                 delayq.head = currp;
  62.                 timersub (&p->dt, left, &t);
  63.             } else {
  64.                 for (p->dt=*left; p && !timercmp(&t, &p->dt, <); q=p, p=p->next)
  65.                     timersub (&t, &t, &p->dt);
  66.                 if (q) q->next = currp;
  67.             }
  68.         } else
  69.             toq (&delayq, currp);
  70.         currp->next = p;
  71.         currp->dt = t;
  72.         *left = delayq.head->dt;
  73.         timerclear(&itime.it_interval);    /* one-shot */
  74.         if (!timerisset(left)) left->tv_usec++;
  75.         setitimer (ITIMER_REAL, &itime, (struct itimerval *)0);
  76.     } else
  77.         readyp (currp);
  78.     reschedp ();
  79. }
  80.  
  81. /*
  82.  * onalarm -- process alarm signals
  83.  */
  84. void onalarm (void)
  85. {
  86.     struct pcb *p;
  87.     struct itimerval itime;
  88.  
  89.     do {
  90.         readyp (hoq (&delayq));
  91.         p = delayq.head;
  92.     } while (p && !timerisset(&p->dt));
  93.     if (p) {
  94.         /* start a new one-shot timer */
  95.         timerclear(&itime.it_interval);
  96.         itime.it_value = p->dt;
  97.         setitimer (ITIMER_REAL, &itime, (struct itimerval *)0);
  98.     }
  99. }
  100.